package cn.nfwx.tv.widget.nfwxplayer;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.Surface;
import android.view.TextureView;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;

import com.hdl.m3u8.M3U8InfoManger;
import com.hdl.m3u8.bean.M3U8;
import com.hdl.m3u8.bean.OnM3U8InfoListener;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import cn.nfwx.tv.events.AppointEvent;
import cn.nfwx.tv.events.PlayEvents;
import cn.nfwx.tv.helper.ThreadHelper;
import cn.nfwx.tv.util.AppUtil;
import cn.nfwx.tv.util.DensityUtil;
import cn.nfwx.tv.util.LogUtil;
import cn.nfwx.tv.util.ScreenUtil;
import tv.danmaku.ijk.media.exo.IjkExoMediaPlayer;
import tv.danmaku.ijk.media.player.AndroidMediaPlayer;
import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;

public class NfwxVideoPlayer extends FrameLayout
        implements INfwxVideoPlayer, OnM3U8InfoListener,
        TextureView.SurfaceTextureListener {

    private static final String TAG = "NfwxVideoPlayer";

    /**
     * IjkPlayer
     **/
    public static final int TYPE_IJK = 111;
    /**
     * MediaPlayer
     **/
    public static final int TYPE_NATIVE = 222;
    /**
     * EXOPlayer
     */
    public static final int TYPE_EXO = 333;


    private int mPlayerType = TYPE_IJK;
    private int mCurrentState = STATE_IDLE;
    private int mCurrentMode = MODE_NORMAL;
    private int mPlayerMode = MODE_SMALLED;

    private Context mContext;
    private AudioManager mAudioManager;
    private IMediaPlayer mMediaPlayer;

    private FrameLayout mContainer;
    private NfwxTextureView mTextureView;
    private NfwxVideoPlayerController mController;
    private SurfaceTexture mSurfaceTexture;
    private Surface mSurface;
    private String mUrl;
    private Map<String, String> mHeaders;
    private int mBufferPercentage;
    private boolean continueFromLastPosition = true;
    private long skipToPosition;

    private int mVideoWidth;
    private int mVideoHeight;

    /**
     * 直播时间
     */
    private long timeCode;

    public NfwxVideoPlayer(Context context) {
        this(context, null);
    }

    public NfwxVideoPlayer(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    private void init() {
        mContainer = new FrameLayout(mContext);
        mContainer.setBackgroundColor(Color.BLACK);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        this.addView(mContainer, params);
    }

    @Override
    public void setUp(String url, Map<String, String> headers) {
        mUrl = url;
        mHeaders = headers;
    }

    @Override
    public void setUp(String url) {
        mUrl = url;
    }

    public NfwxVideoPlayerController getController() {
        return mController;
    }

    public void setController(NfwxVideoPlayerController controller) {
        mContainer.removeView(mController);
        if (mController != null) {
            releasePlayer();
            mController.release();
            mController = null;
        }
        mController = controller;
        mController.init();
        mController.initData();
        mController.reset();
        mController.setVideoPlayer(this);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        mContainer.addView(mController, params);
    }

    /**
     * 设置播放器类型
     *
     * @param playerType IjkPlayer or MediaPlayer.
     */
    @Override
    public void setPlayerType(int playerType) {
        mPlayerType = playerType;
    }

    /**
     * 是否从上一次的位置继续播放
     *
     * @param continueFromLastPosition true从上一次的位置继续播放
     */
    @Override
    public void continueFromLastPosition(boolean continueFromLastPosition) {
        this.continueFromLastPosition = continueFromLastPosition;
    }

    @Override
    public void setSpeed(float speed) {
        if (mMediaPlayer instanceof IjkMediaPlayer) {
            ((IjkMediaPlayer) mMediaPlayer).setSpeed(speed);
        } else {
            LogUtil.d(TAG, "只有IjkPlayer才能设置播放速度");
        }
    }

    @Override
    public void start() {
        start(0);
    }

    @Override
    public void start(long position) {
        LogUtil.e("ttt", "start---" + position);
        skipToPosition = position;
        if (mCurrentState == STATE_IDLE) {
            NfwxVideoPlayerManager.instance().setCurrentVideoPlayer(this);
            initAudioManager();
            initMediaPlayer();
            initTextureView();
            addTextureView();
        } else {
            LogUtil.d(TAG, "NfwxVideoPlayer只有在mCurrentState == STATE_IDLE时才能调用start方法.");
        }
    }

    @Override
    public void reStart() {
        if (mController != null) {
            if (mController.isLive() && !mController.isShift()) {
                mController.reStart();
            } else {
                if (mSurfaceTexture == null) {
                    mController.reStart();
                } else {
                    restart();
                }
            }
        }
    }

    @Override
    public void restart() {
        if (mCurrentState == STATE_PAUSED) {
            mMediaPlayer.start();
            mCurrentState = STATE_PLAYING;
            mController.onPlayStateChanged(mCurrentState);
            LogUtil.d(TAG, "STATE_PLAYING");
        } else if (mCurrentState == STATE_BUFFERING_PAUSED) {
            mMediaPlayer.start();
            mCurrentState = STATE_BUFFERING_PLAYING;
            mController.onPlayStateChanged(mCurrentState);
            LogUtil.d(TAG, "STATE_BUFFERING_PLAYING");
        } else if (mCurrentState == STATE_COMPLETED || mCurrentState == STATE_ERROR) {
            mMediaPlayer.reset();
            openMediaPlayer();
        } else {
            LogUtil.d(TAG, "NiceVideoPlayer在mCurrentState == " + mCurrentState + "时不能调用restart()方法.");
        }
    }

    @Override
    public void pause() {
        if (mCurrentState == STATE_PLAYING) {
            mMediaPlayer.pause();
            mCurrentState = STATE_PAUSED;
            mController.onPlayStateChanged(mCurrentState);
            LogUtil.d(TAG, "STATE_PAUSED");
        }
        if (mCurrentState == STATE_BUFFERING_PLAYING) {
            mMediaPlayer.pause();
            mCurrentState = STATE_BUFFERING_PAUSED;
            mController.onPlayStateChanged(mCurrentState);
            LogUtil.d(TAG, "STATE_BUFFERING_PAUSED");
        }
    }

    @Override
    public void seekTo(long pos) {
        if (mMediaPlayer != null) {
            if (pos >= mMediaPlayer.getDuration()) {
                mCurrentState = STATE_COMPLETED;
                mController.onPlayStateChanged(mCurrentState);
                mContainer.setKeepScreenOn(false);
            } else if (pos <= 0) {
                releasePlayer();
                start();
            } else {
                mCurrentState = STATE_SEEKING_START;
                mController.onPlayStateChanged(mCurrentState);
                mMediaPlayer.seekTo(pos);
            }
        }
    }

    @Override
    public void seekByTimeCode(long timeCode) {
        String timeUrl = mController.getTimesShiftUrl(timeCode);
        if (!TextUtils.isEmpty(timeUrl)) {
            releasePlayer();
            setUp(timeUrl, null);
            start();
        }
    }

    @Override
    public void setVolume(int volume) {
        if (mAudioManager != null) {
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
        }
    }

    @Override
    public void setBright(float bright) {
        Activity activity = AppUtil.scanForActivity(mContext);
        if (activity != null) {
            WindowManager.LayoutParams params = activity.getWindow().getAttributes();
            params.screenBrightness = bright;
            activity.getWindow().setAttributes(params);
        }
    }

    @Override
    public boolean isIdle() {
        return mCurrentState == STATE_IDLE;
    }

    @Override
    public boolean isPreparing() {
        return mCurrentState == STATE_PREPARING;
    }

    @Override
    public boolean isPrepared() {
        return mCurrentState == STATE_PREPARED;
    }

    @Override
    public boolean isBufferingPlaying() {
        return mCurrentState == STATE_BUFFERING_PLAYING;
    }

    @Override
    public boolean isBufferingPaused() {
        return mCurrentState == STATE_BUFFERING_PAUSED;
    }

    @Override
    public boolean isPlaying() {
        return mCurrentState == STATE_PLAYING;
    }

    @Override
    public boolean isPaused() {
        return mCurrentState == STATE_PAUSED;
    }

    @Override
    public boolean isError() {
        return mCurrentState == STATE_ERROR;
    }

    @Override
    public boolean isCompleted() {
        return mCurrentState == STATE_COMPLETED;
    }

    @Override
    public boolean isFullScreen() {
        return mCurrentMode == MODE_FULL_SCREEN;
    }

    @Override
    public boolean isTinyWindow() {
        return mCurrentMode == MODE_TINY_WINDOW;
    }

    @Override
    public boolean isNormal() {
        return mCurrentMode == MODE_NORMAL;
    }

    @Override
    public boolean isClipPause() {
        return mController != null && (mController.isClip() && mController.isHandPause());
    }

    @Override
    public boolean isHandPause() {
        return mController != null && mController.isHandPause();
    }

    @Override
    public boolean isSeeking() {
        return mCurrentState == STATE_SEEKING_START;
    }

    @Override
    public int getMaxVolume() {
        if (mAudioManager != null) {
            return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        }
        return 0;
    }

    @Override
    public int getVolume() {
        if (mAudioManager != null) {
            return mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        }
        return 0;
    }

    @Override
    public float getBright() {
        float value = 0;
        Activity activity = AppUtil.scanForActivity(mContext);
        if (activity != null) {
            value = activity.getWindow().getAttributes().screenBrightness;
        }
        return value;
    }

    @Override
    public long getDuration() {
        return mMediaPlayer != null ? mMediaPlayer.getDuration() : 0;
    }

    @Override
    public long getCurrentPosition() {
        return mMediaPlayer != null ? mMediaPlayer.getCurrentPosition() : 0;
    }

    @Override
    public long getTimeCode() {
        if (mMediaPlayer != null) {
            if (timeCode == 0) {
                return getCurrentPosition();
            } else {
                return (timeCode + getCurrentPosition()) / 1000L;
            }
        } else {
            return 0;
        }
    }

    @Override
    public int getBufferPercentage() {
        return mBufferPercentage;
    }

    @Override
    public float getSpeed(float speed) {
        if (mMediaPlayer instanceof IjkMediaPlayer) {
            return ((IjkMediaPlayer) mMediaPlayer).getSpeed(speed);
        }
        return 0;
    }

    @Override
    public long getTcpSpeed() {
        if (mMediaPlayer instanceof IjkMediaPlayer) {
            return ((IjkMediaPlayer) mMediaPlayer).getTcpSpeed();
        }
        return 0;
    }

    @Override
    public void enterBigedScreen() {
        if (mTextureView != null) {
            mPlayerMode = MODE_BIGED;
            mTextureView.adaptVideoSize(ScreenUtil.getDisplayWidth(mContext), ScreenUtil.getDisplayHeight(mContext));
        }
    }

    @Override
    public void enterSmalledScreen() {
        if (mTextureView != null) {
            if (mVideoWidth != 0 && mVideoHeight != 0) {
                mPlayerMode = MODE_SMALLED;
                mTextureView.adaptVideoSize(mVideoWidth, mVideoHeight);
            }
        }
    }

    private void initAudioManager() {
        if (mAudioManager == null) {
            mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
            if (mAudioManager != null) {
                mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
            }
        }
    }

    private void initMediaPlayer() {
        if (mMediaPlayer == null) {
            switch (mPlayerType) {
                case TYPE_NATIVE:
                    mMediaPlayer = new AndroidMediaPlayer();
                    break;
                case TYPE_EXO:
                    mMediaPlayer = new IjkExoMediaPlayer(mContext);
                    break;
                case TYPE_IJK:
                default:
                    mMediaPlayer = new IjkMediaPlayer();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                        if (isMediaCodecList()) {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1L);
                            }
                        }
                    }
                    //((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 1024L);
                    //((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"max_analyze_duration",1000L);
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1L);
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 1L);
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1L);
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 1L);
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);


                    //((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", "fcc-i420");

                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "analyzeduration", "20000000");
                    ((IjkMediaPlayer) mMediaPlayer).setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "probsize", "4096");

                    mVideoWidth = 0;
                    mVideoHeight = 0;

                    break;
            }
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        }
    }


    private boolean isMediaCodecList() {
        boolean _hasHardAVC = false;
        try {
            _hasHardAVC = hasHardwareCodecForType("video/avc");
            if (!_hasHardAVC) {
                _hasHardAVC = isSupportMediaCodecHardDecoder();
            }
        } catch (Throwable e) {
            _hasHardAVC = false;
        }
        return _hasHardAVC;
    }

    public boolean isSupportMediaCodecHardDecoder() {
        boolean isHardcode = false;
        File file = new File("/system/etc/media_codecs.xml");
        InputStream inFile = null;
        try {
            inFile = new FileInputStream(file);
        } catch (Exception e) {
        }
        if (inFile != null) {
            XmlPullParserFactory pullFactory;
            try {
                pullFactory = XmlPullParserFactory.newInstance();
                XmlPullParser xmlPullParser = pullFactory.newPullParser();
                xmlPullParser.setInput(inFile, "UTF-8");
                int eventType = xmlPullParser.getEventType();
                while (eventType != XmlPullParser.END_DOCUMENT) {
                    String tagName = xmlPullParser.getName();
                    switch (eventType) {
                        case XmlPullParser.START_TAG:
                            if ("MediaCodec".equals(tagName)) {
                                String componentName = xmlPullParser.getAttributeValue(0);

                                if (componentName.startsWith("OMX.")) {
                                    if (!componentName.startsWith("OMX.google.")) {
                                        isHardcode = true;
                                    }
                                }
                            }
                    }
                    eventType = xmlPullParser.next();
                }
            } catch (Exception e) {
            }
        }
        return isHardcode;
    }

    public static boolean hasHardwareCodecForType(String mime) {
        int n;
        MediaCodecList m = null;
        MediaCodecInfo[] infos = null;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            m = new MediaCodecList(MediaCodecList.ALL_CODECS);
            infos = m.getCodecInfos();
            n = infos.length;
        } else {
            n = MediaCodecList.getCodecCount();
        }
        for (int i = 0; i < n; ++i) {
            MediaCodecInfo info;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                info = infos[i];
            } else {
                info = MediaCodecList.getCodecInfoAt(i);
            }
            if (info.isEncoder()) continue;
            String name = info.getName();
            if (name.startsWith("OMX.google.")) continue;

            String[] types = info.getSupportedTypes();
            if (types == null || types.length == 0) continue;
            for (int j = 0; j < types.length; ++j) {
                if (types[j].equals(mime)) return true;
            }
        }
        return false;
    }

    private void initTextureView() {
        LogUtil.e("ttt", "initTextureView");
        if (mTextureView == null) {
            mTextureView = new NfwxTextureView(mContext);
            mTextureView.setSurfaceTextureListener(this);
        }
    }

    private void addTextureView() {
        mContainer.removeView(mTextureView);
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT,
                Gravity.CENTER);
        mContainer.addView(mTextureView, 0, params);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
        if (mSurfaceTexture == null) {
            mSurfaceTexture = surfaceTexture;
            openMediaPlayer();
        } else {
            mTextureView.setSurfaceTexture(mSurfaceTexture);
        }
    }

    private void openMediaPlayer() {
        // 屏幕常亮
        mContainer.setKeepScreenOn(true);
        // 设置监听
        mMediaPlayer.setOnPreparedListener(mOnPreparedListener);
        mMediaPlayer.setOnVideoSizeChangedListener(mOnVideoSizeChangedListener);
        mMediaPlayer.setOnCompletionListener(mOnCompletionListener);
        mMediaPlayer.setOnSeekCompleteListener(mOnSeekCompleteListener);
        mMediaPlayer.setOnErrorListener(mOnErrorListener);
        mMediaPlayer.setOnInfoListener(mOnInfoListener);
        mMediaPlayer.setOnBufferingUpdateListener(mOnBufferingUpdateListener);
        // 设置dataSource
        try {
            if (mController.isLive()) {
                M3U8InfoManger.getInstance().getM3U8Info(mUrl, this);
            } else {
                timeCode = 0;
            }
            mMediaPlayer.setDataSource(mContext, Uri.parse(mUrl), mHeaders);
            if (mSurface == null) {
                mSurface = new Surface(mSurfaceTexture);
            }
            mMediaPlayer.setSurface(mSurface);
            mMediaPlayer.prepareAsync();
            mCurrentState = STATE_PREPARING;
            mController.onPlayStateChanged(mCurrentState);
            LogUtil.d(TAG, "STATE_PREPARING");
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.e("打开播放器发生错误", e.getMessage());
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        return mSurfaceTexture == null;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    }

    private IMediaPlayer.OnPreparedListener mOnPreparedListener
            = new IMediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(IMediaPlayer mp) {
            mCurrentState = STATE_PREPARED;
            mController.onPlayStateChanged(mCurrentState);
            LogUtil.d(TAG, "onPrepared ——> STATE_PREPARED");
            mp.start();
            // 从上次的保存位置播放
            if (continueFromLastPosition) {
                //long savedPlayPosition = NiceUtil.getSavedPlayPosition(mContext, mUrl);
                //mp.seekTo(savedPlayPosition);
            }
            // 跳到指定位置播放
            if (!mController.isLive()) {
                if (skipToPosition != 0) {
                    mp.seekTo(skipToPosition);
                }
            }
        }
    };

    private IMediaPlayer.OnVideoSizeChangedListener mOnVideoSizeChangedListener
            = new IMediaPlayer.OnVideoSizeChangedListener() {
        @Override
        public void onVideoSizeChanged(IMediaPlayer mp, int width, int height, int sar_num, int sar_den) {
            if (mTextureView != null) {
                mVideoWidth = width;
                mVideoHeight = height;
                if (mPlayerMode == MODE_SMALLED) {
                    mTextureView.adaptVideoSize(width, height);
                } else if (mPlayerMode == MODE_BIGED) {
                    mTextureView.adaptVideoSize(ScreenUtil.getDisplayWidth(mContext), ScreenUtil.getDisplayHeight(mContext));
                }
            }
            LogUtil.d(TAG, "onVideoSizeChanged ——> width：" + width + "， height：" + height);
        }
    };

    private IMediaPlayer.OnCompletionListener mOnCompletionListener
            = new IMediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(IMediaPlayer mp) {
            mCurrentState = STATE_COMPLETED;
            mController.onPlayStateChanged(mCurrentState);
            LogUtil.d(TAG, "onCompletion ——> STATE_COMPLETED");
            // 清除屏幕常亮
            mContainer.setKeepScreenOn(false);
        }
    };

    private final IMediaPlayer.OnSeekCompleteListener mOnSeekCompleteListener = new IMediaPlayer.OnSeekCompleteListener() {
        @Override
        public void onSeekComplete(IMediaPlayer iMediaPlayer) {

        }
    };

    private IMediaPlayer.OnErrorListener mOnErrorListener
            = new IMediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(IMediaPlayer mp, int what, int extra) {
            // 直播流播放时去调用mediaPlayer.getDuration会导致-38和-2147483648错误，忽略该错误
            if (what != -38 && what != -2147483648 && extra != -38 && extra != -2147483648) {
                mCurrentState = STATE_ERROR;
                mController.onPlayStateChanged(mCurrentState);
                LogUtil.d(TAG, "onError ——> STATE_ERROR ———— what：" + what + ", extra: " + extra);
            }
            return true;
        }
    };

    private IMediaPlayer.OnInfoListener mOnInfoListener
            = new IMediaPlayer.OnInfoListener() {
        @Override
        public boolean onInfo(IMediaPlayer mp, int what, int extra) {
            if (what == IMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
                // 播放器开始渲染
                if (mCurrentState != STATE_SEEKING_START) {
                    mCurrentState = STATE_PLAYING;
                    mController.onPlayStateChanged(mCurrentState);
                }
                LogUtil.d(TAG, "onInfo ——> MEDIA_INFO_VIDEO_RENDERING_START：STATE_PLAYING");
            } else if (what == IMediaPlayer.MEDIA_INFO_BUFFERING_START) {
                // MediaPlayer暂时不播放，以缓冲更多的数据
                if (mCurrentState == STATE_PAUSED || mCurrentState == STATE_BUFFERING_PAUSED) {
                    mCurrentState = STATE_BUFFERING_PAUSED;
                    mController.onPlayStateChanged(mCurrentState);
                    LogUtil.d(TAG, "onInfo ——> MEDIA_INFO_BUFFERING_START：STATE_BUFFERING_PAUSED");
                } else if (mCurrentState != STATE_SEEKING_START) {
                    mCurrentState = STATE_BUFFERING_PLAYING;
                    mController.onPlayStateChanged(mCurrentState);
                    LogUtil.d(TAG, "onInfo ——> MEDIA_INFO_BUFFERING_START：STASTATE_COMPLETEDTE_BUFFERING_PLAYING");
                }

            } else if (what == IMediaPlayer.MEDIA_INFO_BUFFERING_END) {
                // 填充缓冲区后，MediaPlayer恢复播放/暂停
                if (mCurrentState == STATE_BUFFERING_PLAYING) {
                    mCurrentState = STATE_PLAYING;
                    mController.onPlayStateChanged(mCurrentState);
                    LogUtil.d(TAG, "onInfo ——> MEDIA_INFO_BUFFERING_END： STATE_PLAYING");
                }
                if (mCurrentState == STATE_BUFFERING_PAUSED) {
                    mCurrentState = STATE_PAUSED;
                    mController.onPlayStateChanged(mCurrentState);
                    LogUtil.d(TAG, "onInfo ——> MEDIA_INFO_BUFFERING_END： STATE_PAUSED");
                }
            } else if (what == IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED) {
                // 视频旋转了extra度，需要恢复
                if (mTextureView != null) {
                    mTextureView.setRotation(extra);
                    LogUtil.d(TAG, "视频旋转角度：" + extra);
                }
            } else if (what == IMediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {
                LogUtil.d(TAG, "视频不能seekTo，为直播视频");
            } else if (what == IMediaPlayer.MEDIA_INFO_VIDEO_SEEK_RENDERING_START) {
                mCurrentState = STATE_SEEKING_COMPLETED;
                mController.onPlayStateChanged(mCurrentState);
                if (mController.isHandPause()) {
                    mCurrentState = STATE_PAUSED;
                } else {
                    mCurrentState = STATE_PLAYING;
                }
            } else {
                LogUtil.d(TAG, "onInfo ——> what：" + what);
            }
            return true;
        }
    };

    private IMediaPlayer.OnBufferingUpdateListener mOnBufferingUpdateListener
            = new IMediaPlayer.OnBufferingUpdateListener() {
        @Override
        public void onBufferingUpdate(IMediaPlayer mp, int percent) {
            mBufferPercentage = percent;
        }
    };

    /**
     * 全屏，将mContainer(内部包含mTextureView和mController)从当前容器中移除，并添加到android.R.content中.
     * 切换横屏时需要在manifest的activity标签下添加android:configChanges="orientation|keyboardHidden|screenSize"配置，
     * 以避免Activity重新走生命周期
     */
    @Override
    public void enterFullScreen() {
        if (mCurrentMode == MODE_FULL_SCREEN) return;

        // 隐藏ActionBar、状态栏，并横屏
        //NiceUtil.hideActionBar(mContext);
        AppUtil.scanForActivity(mContext)
                .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        ViewGroup contentView = AppUtil.scanForActivity(mContext)
                .findViewById(android.R.id.content);
        if (mCurrentMode == MODE_TINY_WINDOW) {
            contentView.removeView(mContainer);
        } else {
            this.removeView(mContainer);
        }
        LayoutParams params = new LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        contentView.addView(mContainer, params);

        mCurrentMode = MODE_FULL_SCREEN;
        mController.onPlayModeChanged(mCurrentMode);
        LogUtil.d(TAG, "MODE_FULL_SCREEN");
    }

    /**
     * 退出全屏，移除mTextureView和mController，并添加到非全屏的容器中。
     * 切换竖屏时需要在manifest的activity标签下添加android:configChanges="orientation|keyboardHidden|screenSize"配置，
     * 以避免Activity重新走生命周期.
     *
     * @return true退出全屏.
     */
    @Override
    public boolean exitFullScreen() {
        if (mCurrentMode == MODE_FULL_SCREEN) {
            //NiceUtil.showActionBar(mContext);
            AppUtil.scanForActivity(mContext)
                    .setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

            ViewGroup contentView = AppUtil.scanForActivity(mContext)
                    .findViewById(android.R.id.content);
            contentView.removeView(mContainer);
            LayoutParams params = new LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            this.addView(mContainer, params);

            mCurrentMode = MODE_NORMAL;
            mController.onPlayModeChanged(mCurrentMode);
            LogUtil.d(TAG, "MODE_NORMAL");
            return true;
        }
        return false;
    }

    /**
     * 进入小窗口播放，小窗口播放的实现原理与全屏播放类似。
     */
    @Override
    public void enterTinyWindow() {
        if (mCurrentMode == MODE_TINY_WINDOW) return;
        this.removeView(mContainer);

        ViewGroup contentView = (ViewGroup) AppUtil.scanForActivity(mContext)
                .findViewById(android.R.id.content);
        // 小窗口的宽度为屏幕宽度的60%，长宽比默认为16:9，右边距、下边距为8dp。
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                (int) (ScreenUtil.getDisplayWidth(mContext) * 0.6f),
                (int) (ScreenUtil.getDisplayWidth(mContext) * 0.6f * 9f / 16f));
        params.gravity = Gravity.BOTTOM | Gravity.END;
        params.rightMargin = DensityUtil.dip2px(mContext, 8f);
        params.bottomMargin = DensityUtil.dip2px(mContext, 8f);

        contentView.addView(mContainer, params);

        mCurrentMode = MODE_TINY_WINDOW;
        mController.onPlayModeChanged(mCurrentMode);
        LogUtil.d(TAG, "MODE_TINY_WINDOW");
    }

    /**
     * 退出小窗口播放
     */
    @Override
    public boolean exitTinyWindow() {
        if (mCurrentMode == MODE_TINY_WINDOW) {
            ViewGroup contentView = AppUtil.scanForActivity(mContext)
                    .findViewById(android.R.id.content);
            contentView.removeView(mContainer);
            LayoutParams params = new LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
            this.addView(mContainer, params);

            mCurrentMode = MODE_NORMAL;
            mController.onPlayModeChanged(mCurrentMode);
            LogUtil.d(TAG, "MODE_NORMAL");
            return true;
        }
        return false;
    }

    @Override
    public void releasePlayer() {
        if (mAudioManager != null) {
            mAudioManager.abandonAudioFocus(null);
            mAudioManager = null;
        }

        if (mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
        mContainer.removeView(mTextureView);
        if (mSurface != null) {
            mSurface.release();
            mSurface = null;
        }
        if (mSurfaceTexture != null) {
            mSurfaceTexture.release();
            mSurfaceTexture = null;
        }
        mCurrentState = STATE_IDLE;
    }

    @Override
    public void release() {
        // 保存播放位置
//        if (isPlaying() || isBufferingPlaying() || isBufferingPaused() || isPaused()) {
//            NiceUtil.savePlayPosition(mContext, mUrl, getCurrentPosition());
//        } else if (isCompleted()) {
//            NiceUtil.savePlayPosition(mContext, mUrl, 0);
//        }
        // 退出全屏或小窗口
        if (isFullScreen()) {
            exitFullScreen();
        }
        if (isTinyWindow()) {
            exitTinyWindow();
        }
        mCurrentMode = MODE_NORMAL;

        // 释放播放器
        releasePlayer();

        // 恢复控制器
        if (mController != null) {
            mController.release();
            mController.reset();
        }

        M3U8InfoManger.getInstance().release();
    }

    @Override
    public void clearScreen() {
        mContainer.removeView(mTextureView);
        if (mSurface != null) {
            mSurface.release();
            mSurface = null;
        }
        if (mSurfaceTexture != null) {
            mSurfaceTexture.release();
            mSurfaceTexture = null;
        }
    }

    @Override
    public boolean onBackPressed() {
        if (mController != null) {
            return mController.onBackPressd();
        }
        return true;
    }

    @Override
    public void onSuccess(M3U8 m3U8) {
        try {
            if (!m3U8.getTsList().isEmpty()) {
                String fileName;
                if (m3U8.getTsList().size() > 3) {
                    fileName = m3U8.getTsList().get(m3U8.getTsList().size() - 3).getFileName();
                } else {
                    fileName = m3U8.getTsList().get(0).getFileName();
                }
                if (!TextUtils.isEmpty(fileName) && fileName.startsWith("live-") && fileName.endsWith(".ts")) {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
                    String timeStr = fileName.substring("live-".length(), fileName.lastIndexOf(".ts"));
                    try {
                        Date date = dateFormat.parse(timeStr);
                        timeCode = date.getTime();
                    } catch (Exception e) {
                        timeCode = System.currentTimeMillis();
                    }
                }
            }
        } catch (Exception e) {
            timeCode = System.currentTimeMillis();
        }
    }

    @Override
    public void onStart() {

    }

    @Override
    public void onError(Throwable errorMsg) {

    }

    /**
     * 网络改变
     *
     * @param networkType
     */
    public void onNetworkChange(int networkType) {
        mController.onNetworkChange(networkType);
    }

    /**
     * 播放事件
     *
     * @param events
     */
    public void playEventBus(PlayEvents events) {
        if (mController != null) {
            mController.playEventBus(events);
        }
    }

    /**
     * 预约节目
     *
     * @param event
     */
    public void appiontEvent(AppointEvent event) {
        if (mController != null) {
            mController.appiontEvent(event);
        }
    }

    /**
     * @param intent
     */
    public void onReceive(Intent intent) {
        if (mController != null) {
            mController.onReceive(intent);
        }
    }
}

